package makabakaquestionnaire.zutsoftware.framework.security;


import com.fasterxml.jackson.databind.ObjectMapper;
import makabakaquestionnaire.zutsoftware.framework.security.Service.AuthLoginService;
import makabakaquestionnaire.zutsoftware.framework.security.fliter.JwtAuthenticationTokenFilter;
import makabakaquestionnaire.zutsoftware.framework.security.handle.AccessDeniedHandlerImpl;
import makabakaquestionnaire.zutsoftware.framework.security.handle.LoginFailHandlerImpl;
import makabakaquestionnaire.zutsoftware.framework.security.handle.LogoutSuccessHandlerImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

@Configuration
@EnableWebSecurity
//@EnableGlobalMethodSecurity(securedEnabled = true) // 控制权限注解
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private AuthLoginService userDetailsService;

    /**
     * 退出处理类
     */
    @Autowired
    private LogoutSuccessHandlerImpl logoutSuccessHandler;

    /**
     * 权限不足处理类
     */
    @Autowired
    private AccessDeniedHandlerImpl accessDeniedHandler;
    /**
     * 认证失败处理类
     */
    @Autowired
    private LoginFailHandlerImpl loginFailHandler;

    /**
     * 解决 无法直接注入 AuthenticationManager
     *
     * @return
     * @throws Exception
     */
    /**
     * token认证过滤器
     */
    @Autowired
    private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception
    {
        return super.authenticationManagerBean();
    }
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(password());

    }

    @Autowired
    private ObjectMapper objectMapper;


    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
                .httpBasic()
                    .authenticationEntryPoint((request,response,authException) -> {
                    response.setContentType("application/json;charset=utf-8");
                    response.setStatus(HttpServletResponse.SC_FORBIDDEN);
                    PrintWriter out = response.getWriter();
                    Map<String,Object> map = new HashMap<String,Object>();
                    map.put("code",403);
                    map.put("message","未登录");
                    out.write(objectMapper.writeValueAsString(map));
                    out.flush();
                    out.close();
                })
                .and()
                .authorizeRequests()
                .antMatchers("/admin/**").hasRole("admin")    //配置权限
                //放行swagger-ui页面
                .antMatchers("/swagger-ui.html").permitAll() // swagger任意访问
                .antMatchers("/swagger-resources/**").permitAll()
                .antMatchers("/webjars/**").permitAll()
                .antMatchers("/v2/**").permitAll()
                .antMatchers("/api/**").permitAll()
                .antMatchers("/project/result/save").permitAll()
                .antMatchers("/project/preview/**").permitAll()
                .antMatchers("/myLogin.html/**").permitAll()
                .antMatchers("/doLogin","/captchaImage").permitAll()
                .requestMatchers(CorsUtils::isPreFlightRequest).permitAll() // 跨域配置这句比较重要，放过 option 请求
                //.anyRequest().authenticated() //必须授权才能范围
                .and()
                .formLogin() //使用自带的登录// 开启登录表单功能
                //.loginPage("/myLogin.html") // 使用自定义的登录页面，不再使用SpringSecurity提供的默认登录页
                .permitAll()
                .and().exceptionHandling().authenticationEntryPoint(loginFailHandler)
                //.failureHandler(loginFailHandler)
//                .failureHandler((request,response,ex) -> {
//                    response.setContentType("application/json;charset=utf-8");
//                    response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
//                    PrintWriter out = response.getWriter();
//                    Map<String,Object> map = new HashMap <String,Object>();
//                    map.put("code",401);
//                    if (ex instanceof UsernameNotFoundException || ex instanceof BadCredentialsException) {
//                        map.put("message","用户名或密码错误");
//                    } else if (ex instanceof DisabledException) {
//                        map.put("message","账户被禁用");
//                    } else {
//                        map.put("message","登录失败!");
//                    }
//                    out.write(objectMapper.writeValueAsString(map));
//                    out.flush();
//                    out.close();
//                })
                //登录成功，返回json
//                .successHandler((request,response,authentication) -> {
//                    Map<String,Object> map = new HashMap<String,Object>();
//                    map.put("code",200);
//                    map.put("message","登录成功");
//                    map.put("data",authentication.getPrincipal());
//                    response.setHeader("Access-Control-Allow-Origin",request.getHeader("Origin"));
//                    response.setHeader("Access-Control-Allow-Credentials","true");
//                    response.setContentType("application/json;charset=utf-8");
//                    PrintWriter out = response.getWriter();
//                    out.write(objectMapper.writeValueAsString(map));
//                    out.flush();
//                    out.close();
//                })
                .and()
                .exceptionHandling()
                //没有权限，返回json
                .accessDeniedHandler(accessDeniedHandler)
                .and()
                .logout()
                //退出成功，返回json
                .logoutSuccessHandler(logoutSuccessHandler)
                .permitAll().
                and().cors().
                and().csrf().disable();
        httpSecurity.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
    }



    @Bean
    PasswordEncoder password(){
        return new BCryptPasswordEncoder();
    }
}
